import { Injectable } from '@angular/core';
import { FileInfo } from '../model/file-info';
import {ExecActionInterface} from "./exec-action-interface";
import {ExecActionMainService} from "./exec-action-main.service";
import {ParamDef} from "../model/param-def";
import {MatchExecActionService} from "./match-exec-action.service";
import {SystemUtilsService} from "../service/system-utils.service";
import { Buffer } from 'buffer';
import {ExifReader} from "../ts/exif-reader";
import Decimal from 'decimal.js';
@Injectable({
  providedIn: 'root'
})
export class ImageExifExecActionService extends ExecActionInterface{
  exifRead = new ExifReader()

  constructor(matchExecAction:MatchExecActionService,protected fileUtils:SystemUtilsService) {
    super("解析图片Exif信息","imgExif")
    matchExecAction.addMatchItem("拍摄时间","imgExif.DateTimeOriginal")
    matchExecAction.addMatchItem("相机厂家","imgExif.Make")
    matchExecAction.addMatchItem("相机型号","imgExif.Model")
    matchExecAction.addMatchItem("拍摄地点GPS","imgExif.Gps")
    matchExecAction.addMatchItem("照片处理软件","imgExif.Software")
    matchExecAction.addMatchItem("照片修改时间","imgExif.ModifyDate")
  }


   async exec(fileInfo: FileInfo, param: any): Promise<any>{
    let data = await this.fileUtils.getFileInfoData(fileInfo)
    // let tags = Exif.get
    let tags =  await this.readExif(fileInfo.filePath,null)
     if (tags == null){
       return false
     }
     let exif ={
       Make:tags.image.Make,
       Model:tags.image.Model,
       Software:tags.image.Software,
       ModifyDate:tags.image.ModifyDate,
       DateTimeOriginal:tags.exif.DateTimeOriginal,
       DateTimeDigitized:tags.exif.DateTimeDigitized,
       Gps:this.getGpsInfo(tags),
     }
     fileInfo.imgExif=exif
    return exif
  }

  private getGpsInfo(tags:any) {
    if (tags.gps.GPSLatitude == null || tags.gps.GPSLongitude == null){
      return null
    }
    let lat = this.getGpsNumber(tags.gps.GPSLatitude, tags.gps.GPSLatitudeRef)
    let  lon = this.getGpsNumber(tags.gps.GPSLongitude, tags.gps.GPSLongitudeRef)
    return {
      Latitude: lat,
      Longitude: lon,
      str:`${lon},${lat}`
    };
  }

  public getGpsNumber(gpsArray:number[],type:string):string{
    let a =new Decimal(gpsArray[0])
    let b =new Decimal(gpsArray[1])
    let c =new Decimal(gpsArray[2])

    let point = c.div(60).add(b).div(60).add(a)
    if (type =='S' || type =='W'){
      return point.mul(-1).toString();
    }
    return  point.toString()
  }




  public async readExif (filename:string, maxIterations:boolean|number|null) {
    if (maxIterations === true) { // former isDeepSearch boolean argument
      maxIterations = Number.MAX_SAFE_INTEGER;
    }
    if (maxIterations === null) {
      maxIterations = 1;
    }
    let fd  = await this.fileUtils.getPromisesFs().open(filename, 'r')

    let buffer = new Buffer(512);
    let exifBuffer = await this.searchExif(fd, buffer, 0, typeof maxIterations === "number" ? maxIterations :1)
    if (exifBuffer != null){
      return this.exifRead.read(exifBuffer)
    }
    await fd.close();
    return null
  }

  public async  searchExif (fd:any, buffer:Buffer, fileOffset:number, remainingIterations:number): Promise<Buffer|null> {
    let offset = 0, length = buffer.length;
    let  rs = await fd.read(buffer,0,length,null)
    if (!rs.bytesRead) {
      return null;
    }
    while (offset < length) {
      if (buffer[offset++] == 0xFF && buffer[offset] == 0xE1) {
        let exifBuffer = new Buffer(buffer.readUInt16BE(++offset));

        rs= await fd.read( exifBuffer, 0, exifBuffer.length, fileOffset + offset + 2);
        return rs.buffer
      }
    }
    return remainingIterations > 1 ? this.searchExif(fd, buffer, fileOffset + length, remainingIterations - 1) : null;
  }
}

